#ifndef _AMERICO_DYNAMIC_STATIC_ARRAY_H_
#define _AMERICO_DYNAMIC_STATIC_ARRAY_H_

#include "DL_Debug.h"

#pragma warning (push)
#pragma warning (disable: 4996)

namespace Utilities
{
	template <class Type, typename CountType=unsigned int>
	class DynamicStaticArray
	{
	private:
		Type *myContainer;
		CountType mySize;

	public:
		DynamicStaticArray();
		DynamicStaticArray(const CountType &aSize);
		DynamicStaticArray(const DynamicStaticArray &aStaticArray);
		virtual ~DynamicStaticArray();

		void Init(const CountType &aSize);
		void ReInit(const CountType &aSize);

		DynamicStaticArray &operator=(const DynamicStaticArray &aStaticArray);

		inline const Type &operator[](const CountType &anIndex) const;
		inline Type &operator[](const CountType &anIndex);

		CountType size() const { return mySize; }
		inline void Insert(const CountType &anIndex, const Type &anObject);
		inline void DeleteAll();
	};

	template <class Type, typename CountType>
	DynamicStaticArray<Type, CountType>::DynamicStaticArray()
	{
		myContainer = 0;
		mySize = 0;
	}
	template <class Type, typename CountType>
	DynamicStaticArray<Type, CountType>::DynamicStaticArray(const CountType &aSize)
	{
		myContainer = 0;
		mySize = 0;
		Init(aSize);
	}
	template <class Type, typename CountType>
	DynamicStaticArray<Type, CountType>::DynamicStaticArray(const DynamicStaticArray &aDynamicStaticArray)
	{
		myContainer = 0;
		mySize = 0;
		Init(aDynamicStaticArray.mySize);
		for(unsigned int index=0; index<mySize; index++)
		{
			myContainer[index] = aDynamicStaticArray.myContainer[index];
		}
	}
	template <class Type, typename CountType>
	DynamicStaticArray<Type, CountType>::~DynamicStaticArray()
	{
		delete [] myContainer;
		mySize = 0;
	}
	template <class Type, typename CountType>
	void DynamicStaticArray<Type, CountType>::Init(const CountType &aSize)
	{
		DL_CHK_ASSERT(myContainer==0, "Array already initialized!");
		delete [] myContainer;
		mySize = aSize;
		myContainer = new Type[mySize];
	}

	template <class Type, typename CountType>
	void DynamicStaticArray<Type, CountType>::ReInit(const CountType &aSize)
	{
		DL_CHK_ASSERT(myContainer != 0, "Use of an undefined array");
		delete [] myContainer;
		mySize = aSize;
		myContainer = new Type[mySize];
	}

	template <class Type, typename CountType>
	DynamicStaticArray<Type, CountType> &DynamicStaticArray<Type, CountType>::operator=(const DynamicStaticArray &aDynamicStaticArray)
	{
		CountType size = mySize;
		if (aDynamicStaticArray.mySize<mySize)
		{
			size = aDynamicStaticArray.mySize;
		}
		for(unsigned int index=0; index<size; index++)
		{
			myContainer[index] = aDynamicStaticArray.myContainer[index];
		}
		return *this;
	}
	template <class Type, typename CountType>
	inline const Type &DynamicStaticArray<Type, CountType>::operator[](const CountType &anIndex) const
	{
		if ((anIndex<0) || (anIndex>=mySize))
		{
			char buffer[40];
			sprintf(buffer, "Error: Index Out Of Bounds! (%d from %d)", anIndex, mySize);
			DL_ASSERT(buffer);
		}
		return myContainer[anIndex];
	}
	template <class Type, typename CountType>
	inline Type &DynamicStaticArray<Type, CountType>::operator[](const CountType &anIndex)
	{
		if ((anIndex<0) || (anIndex>=mySize))
		{
			char buffer[40];
			sprintf(buffer, "Error: Index Out Of Bounds! (%d from %d)", anIndex, mySize);
			DL_ASSERT(buffer);
		}
		return myContainer[anIndex];
	}
	template <class Type, typename CountType>
	inline void DynamicStaticArray<Type, CountType>::Insert(const CountType &anIndex, const Type &anObject)
	{
		if ((anIndex<0) || (anIndex>=mySize))
		{
			char buffer[40];
			sprintf(buffer, "Error: Index Out Of Bounds! (%d from %d)", anIndex, mySize);
			DL_ASSERT(buffer);
		}
		memmove(myContainer+anIndex+1, myContainer+anIndex, (mySize-anIndex-1)*sizeof(Type));
		myContainer[anIndex] = anObject;
	}
	template <class Type, typename CountType>
	inline void DynamicStaticArray<Type, CountType>::DeleteAll()
	{
		for(unsigned int index=0; index<mySize; index++)
		{
			delete myContainer[index];
		}
	}
};
namespace Utils=Utilities;
#pragma warning (pop)

#endif
